package com.hodge.login;

import com.hodge.web.entity.TabUser;
import com.hodge.web.entity.UserVO;
import com.hodge.web.service.UserInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 自定义用户校验机制
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class MyAuthenticationProvider implements AuthenticationProvider {

    private final UserInfoService userInfoService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 获取表单输入中返回的用户名;
        String username = (String) authentication.getPrincipal();
        // 获取表单中输入的密码；
        String password = (String) authentication.getCredentials();
        // 这里调用我们的自己写的获取用户的方法；
        TabUser userInfo = userInfoService.getByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("账号未找到"));

        // 这里判断账号是否冻结
        if (userInfo.getLocked()) {
            throw new LockedException("账号已冻结");
        }
        // 这里判断密码是否正确，密码使用 BCryptPasswordEncoder 进行加密
//        if (!new BCryptPasswordEncoder().matches(password, userInfo.getPassword())) {
        if (!userInfo.getPassword().equals(password)) {
            throw new BadCredentialsException("密码不正确");
        }
        UserVO details = userInfoService.getDetails(userInfo.getId());

        List<SimpleGrantedAuthority> authorityList = details.getPermissions().stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());

        // 构建返回的用户登录成功的token
        return new UsernamePasswordAuthenticationToken(details, password, authorityList);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }
}